/* *****************************************************************************************************************************
 * (c) J@mBeL.net 2010-2015
 * Author: John Ambeliotis
 * Created: 24 Apr. 2010
 *
 * License:
 *  This file is part of Project jaNET.

    Project jaNET is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Project jaNET is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Project jaNET. If not, see <http://www.gnu.org/licenses/>. */

using System;
using System.Xml;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Text;
using System.Globalization;

namespace libJanet
{
    internal struct OperatingSystem
    {
        internal enum Type
        {
            Windows,
            Unix,
            MacOS,
            Unknown
        }

        internal static Type Version
        {
            get { return getOSversion(); }
        }

        private static Type getOSversion()
        {
            switch (Environment.OSVersion.Platform)
            {
                case PlatformID.Unix:
                    return Type.Unix;
                case PlatformID.Win32NT:
                case PlatformID.Win32S:
                case PlatformID.Win32Windows:
                case PlatformID.WinCE:
                case PlatformID.Xbox:
                    return Type.Windows;
                case PlatformID.MacOSX:
                    return Type.MacOS;
            }
            return Type.Unknown;
        }
    }

    public static class Methods
    {
        /// <summary>
        /// returns library's copyright.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/>
        /// </returns>
        private static string getCopyright()
        { return "jaNET Framework [Version 0.2.6.557]\r\nCopyright (c) 2010-" + DateTime.Now.Year + " J@mBeL.net"; }

        private static string getWinPath()
        { return Directory.GetCurrentDirectory().ToString(); }

        private static string getLinuxPath()
        { return Environment.CommandLine.Substring(0, Environment.CommandLine.LastIndexOf("/")).ToString(); }

        /// <summary>
        /// determine OS and returns Linux/Windows formatted path of the application.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/>
        /// </returns>
        public static string getApplicationPath()
        {
            string Path = string.Empty;

            if (OperatingSystem.Version == OperatingSystem.Type.Unix || 
                OperatingSystem.Version == OperatingSystem.Type.MacOS)
                    Path = getLinuxPath() + "/";
            else if (OperatingSystem.Version == OperatingSystem.Type.Windows)
                Path = getWinPath() + @"\";

            return Path;
        }

        internal static string ToHour24(this string hour)
        {
            DateTime dt = DateTime.ParseExact(hour, "h:mm tt",
                                        CultureInfo.InvariantCulture);
            return String.Format("{0:HH:mm}", dt);
        }

        internal static string FixScheduleDate(this string date)
        {
            try
            {
                var dt = DateTime.ParseExact(date.Replace("-", "/").Replace(".", "/"), "dd/MM/yyyy", 
                                        CultureInfo.InvariantCulture);
                return dt.ToString("d/M/yyyy", CultureInfo.InvariantCulture);
            }
            catch {
                return date;
            }
        }

        internal static string getPartOfDay(bool salute)
        {
            if (DateTime.Now.Hour < 6)
                if (salute) return "morning";
                else return "midnight";

            else if (DateTime.Now.Hour < 12)
                return "morning";

            else if (DateTime.Now.Hour < 18)
                return "afternoon";

            else if (DateTime.Now.Hour < 20)
                return "evening";

            else if (DateTime.Now.Hour < 24)
                if (salute) return "evening";
                else return "night";

            else return string.Empty;
        }
        
        internal static string getSalute()
        {
            return getPartOfDay(true);
        }
        
        internal static string getTime()
        {
            return (string.Format("{0:t}", DateTime.Now));
        }
        
        internal static string getTime24()
        {
            return (string.Format("{0:HH:mm}", DateTime.Now));
        }
        
        internal static string getHour()
        {
            return (string.Format("{0:HH}", DateTime.Now));
        }
        
        internal static string getMinute()
        {
            return (string.Format("{0:mm}", DateTime.Now));
        }
        
        internal static string getDate()
        {
            return (string.Format("{0:M}", DateTime.Now));
        }
        
        internal static string getCalendarDate()
        {
            return (string.Format("{0:d/M/yyyy}", DateTime.Now));
        }
        
        internal static string getDay()
        {
            return (DateTime.Now.DayOfWeek.ToString());
        }
        
        internal static string getCalendarDay()
        {
            return (DateTime.Now.Day.ToString());
        }
        
        internal static string getCalendarMonth()
        {
            return (DateTime.Now.Month.ToString());
        }
        
        internal static string getCalendarYear()
        {
            return (DateTime.Now.Year.ToString());
        }
        
        internal static string WhoAmI()
        {
            return Environment.UserName;
        }
        
        internal static string getEvent(string eventID)
        {
            try {
                return Queries.Xml.AppConfigQuery(
                    ApplicationSettings.ApplicationStructure.SystemEventsRoot +
                    "/event[@id='" + eventID + "']").Item(0).InnerText;
            }
            catch {
                return string.Empty;
            }
        }
        
        internal static XmlNodeList getMailHeaders()
        {
            return Queries.Xml.AppConfigQuery("jaNET/System/Alerts/MailHeaders");
        }
        
        internal static XmlNodeList getInstructionSet(string InstructionID)
        {
            return Queries.Xml.AppConfigQuery(
                ApplicationSettings.ApplicationStructure.SystemInstructionsRoot +
                "/InstructionSet[@id='" + InstructionID + "']");
        }
        
        internal static XmlNodeList getXmlElementList(string xPath, string elementName)
        {
            return Queries.Xml.AppConfigQuery(xPath + "/" + elementName);
        }

        private static bool hasInternetConnection(string host)
        {
            try
            {
                if (host == string.Empty)
                    host = "http://www.google.com";
                using (var client = new WebClient())
                    using (var stream = client.OpenRead(host))
                        return true;
            }
            catch {
                return false;
            }
        }

        internal static bool hasInternetConnection()
        {
            return hasInternetConnection(string.Empty);
        }

        // Throw exception in linux, need solution
        internal static bool Ping(string host = null)
        {
            try
            {
                bool network_available = NetworkInterface.GetIsNetworkAvailable();
                bool stat = false;

                if (network_available)
                {
                    if (OperatingSystem.Version == OperatingSystem.Type.Windows)
                    {
                        Ping pingSender = new Ping();
                        String address = host; //IPAddress.Loopback;

                        // Create a buffer of 32 bytes of data to be transmitted. 
                        string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
                        byte[] buffer = Encoding.ASCII.GetBytes(data);

                        // Wait 5 seconds for a reply. 
                        int timeout = 5000;
                        PingReply reply = pingSender.Send(address, timeout, buffer);

                        if (reply.Status == IPStatus.Success)
                        {
                            stat = true;
                            /*Console.WriteLine("Address: {0}", reply.Address.ToString());
                            Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
                            Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
                            Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
                            Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);*/
                        }
                        else
                        {
                            stat = true;
                            //Console.WriteLine(reply.Status);
                        }
                    }
                    else
                    {
                        // Dummy implementation, for test purposes until I find a solution
                        string p = Process.Start("ping", " -c 3 " + host);
                        if (!p.Contains("Destination Host Unreachable"))
                            stat = true;
                    }
                }
                return stat;
            }
            catch {
                return false;
            }
        }
        
        internal static string ToValues(this string context)
        {
            if (context.Contains("%exit%") || context.Contains("%quit%"))
            {
                Listeners.DeactivateSerialPort();
                Parser.ParserState = false;
                context = context.Replace("%exit%", string.Empty).Replace("%quit%", string.Empty);
            }
            if (context.Contains("%clear%") || context.Contains("%cls%"))
            {
                Console.Clear();
                context = context.Replace("%clear%", string.Empty).Replace("%cls%", string.Empty);
            }
            if (context.Contains("%mute%"))
            {
                Parser.Mute = true;
                context = context.Replace("%mute%", string.Empty);
            }
            if (context.Contains("%unmute%"))
            {
                Parser.Mute = false;
                context = context.Replace("%unmute%", string.Empty);
            }
            if (context.Contains("%inet%") || context.Contains("%inetcon%"))
            {
                String con = hasInternetConnection().ToString();
                context = context.Replace("%inet%", con).Replace("%inetcon%", con);
            }
            if (context.Contains("%gmailcount%") || context.Contains("%gcount%"))
                context = context.Replace("%gmailcount%", new Net.Mail().GmailCheck(true).ToString())
                                 .Replace("%gcount%", new Net.Mail().GmailCheck(true).ToString());
            if (context.Contains("%gmailreader%") || context.Contains("%gmailheaders%") || context.Contains("%greader%") || context.Contains("%gheaders%"))
                context = context.Replace("%gmailreader%", new Net.Mail().GmailCheck(false).ToString())
                                 .Replace("%gmailheaders%", new Net.Mail().GmailCheck(false).ToString())
                                 .Replace("%greader%", new Net.Mail().GmailCheck(false).ToString())
                                 .Replace("%gheaders%", new Net.Mail().GmailCheck(false).ToString());
            if (context.Contains("%pop3count%"))
                context = context.Replace("%pop3count%", new Net.Mail().Pop3Check().ToString());
            if (context.Contains("%user%") || context.Contains("%whoami%"))
            {
                String whoami = WhoAmI();
                context = context.Replace("%user%", whoami).Replace("%whoami%", whoami);
            }
            if (context.Contains("%usercheckin%") || context.Contains("%checkin%"))
            {
                User.Status = true;
                context = context.Replace("%usercheckin%", string.Empty).Replace("%checkin%", string.Empty);
            }
            if (context.Contains("%usercheckout%") || context.Contains("%checkout%"))
            {
                User.Status = false;
                context = context.Replace("%usercheckout%", string.Empty).Replace("%checkout%", string.Empty);
            }
            if (context.Contains("%time%"))
                context = context.Replace("%time%", getTime());
            if (context.Contains("%time24%"))
                context = context.Replace("%time24%", getTime24());
            if (context.Contains("%hour%"))
                context = context.Replace("%hour%", getHour());
            if (context.Contains("%minute%"))
                context = context.Replace("%minute%", getMinute());
            if (context.Contains("%date%"))
                context = context.Replace("%date%", getDate());
            if (context.Contains("%calendardate%"))
                context = context.Replace("%calendardate%", getCalendarDate());
            if (context.Contains("%day%"))
                context = context.Replace("%day%", getDay());
            if (context.Contains("%calendarday%"))
                context = context.Replace("%calendarday%", getCalendarDay());
            if (context.Contains("%calendarmonth%"))
                context = context.Replace("%calendarmonth%", getCalendarMonth());
            if (context.Contains("%calendaryear%"))
                context = context.Replace("%calendaryear%", getCalendarYear());
            if (context.Contains("%salute%"))
                context = context.Replace("%salute%", getSalute());
            if (context.Contains("%daypart%") || context.Contains("%partofday%"))
            {
                String daypart = getPartOfDay(false);
                context = context.Replace("%daypart%", daypart).Replace("%partofday%", daypart);
            }
            if (context.Contains("%todayday%"))
                context = context.Replace("%todayday%", new Weather().TodayDay);
            if (context.Contains("%todayconditions%"))
                context = context.Replace("%todayconditions%", new Weather().TodayConditions);
            if (context.Contains("%todaylow%"))
                context = context.Replace("%todaylow%", new Weather().TodayLow);
            if (context.Contains("%todayhigh%"))
                context = context.Replace("%todayhigh%", new Weather().TodayHigh);
            if (context.Contains("%tomorrowday%"))
                context = context.Replace("%tomorrowday%", new Weather().TomorrowDay);
            if (context.Contains("%tomorrowconditions%"))
                context = context.Replace("%tomorrowconditions%", new Weather().TomorrowConditions);
            if (context.Contains("%tomorrowlow%"))
                context = context.Replace("%tomorrowlow%", new Weather().TomorrowLow);
            if (context.Contains("%tomorrowhigh%"))
                context = context.Replace("%tomorrowhigh%", new Weather().TomorrowHigh);
            if (context.Contains("%whereami%") || context.Contains("%userstat%") || context.Contains("%userstatus%"))
                if (User.Status)
                    context = context.Replace("%whereami%", "present").Replace("%userstat%", "present").Replace("%userstatus%", "present");
                else
                    context = context.Replace("%whereami%", "absent").Replace("%userstat%", "absent").Replace("%userstatus%", "absent");
            if (context.Contains("%about%") || context.Contains("%copyright%"))
                context = context.Replace("%about%", getCopyright()).Replace("%copyright%", getCopyright());
                
            // If Event
            if (context.Contains("%~>"))
            {
                Parser.Parse(getEvent(context.Replace("%~>", string.Empty).Replace("%", string.Empty)));
                context = context.Replace(context, string.Empty);
            }
            
            return context;
        }

        internal static string AddToXML(InstructionSet newElement, string xPath, string elementName)
        {
            try
            {
                string path = getApplicationPath() + "AppConfig.xml";
                
                XmlDocument xmldoc = new XmlDocument();
                using (XmlReader xmlReader = XmlReader.Create(path))
                    xmldoc.Load(xmlReader);
				
                File.Copy(path, path + ".bak", true);
                File.Delete(path);
                
                XmlNode xmlnode = xmldoc.SelectSingleNode(xPath); //"jaNET/Instructions");
                // InstructionSet
                XmlElement NewElement = xmldoc.CreateElement(elementName); //("InstructionSet");
                // ID
                XmlAttribute NewAttributeID = xmldoc.CreateAttribute("id");
				NewAttributeID.Value = newElement.Id;
                // Category
                XmlAttribute NewAttributeCateg = xmldoc.CreateAttribute("categ");
                NewAttributeCateg.Value = newElement.Category;
                // Header
                XmlAttribute NewAttributeHeader = xmldoc.CreateAttribute("header");
                NewAttributeHeader.Value = newElement.Header;
                // Short Description
                XmlAttribute NewAttributeShortDescr = xmldoc.CreateAttribute("shortdescr");
                NewAttributeShortDescr.Value = newElement.ShortDescription;
                // Description
                XmlAttribute NewAttributeDescr = xmldoc.CreateAttribute("descr");
                NewAttributeDescr.Value = newElement.Description;
                // Thumbnail
                XmlAttribute NewAttributeImg = xmldoc.CreateAttribute("img");
                NewAttributeImg.Value = newElement.ThumbnailUrl;
                // Real Time
                XmlAttribute NewAttributeRealTime = xmldoc.CreateAttribute("realtime");
                NewAttributeRealTime.Value = newElement.RealTime;
                // Action
                NewElement.InnerText = newElement.Action;
                
                if (NewAttributeID.Value != string.Empty)
                    NewElement.SetAttributeNode(NewAttributeID);
                if (NewAttributeCateg.Value != string.Empty)
                    NewElement.SetAttributeNode(NewAttributeCateg);
                if (NewAttributeHeader.Value != string.Empty)
                    NewElement.SetAttributeNode(NewAttributeHeader);
                if (NewAttributeShortDescr.Value != string.Empty)
                    NewElement.SetAttributeNode(NewAttributeShortDescr);
                if (NewAttributeDescr.Value != string.Empty)
                    NewElement.SetAttributeNode(NewAttributeDescr);
                if (NewAttributeImg.Value != string.Empty)
                    NewElement.SetAttributeNode(NewAttributeImg);
                if (NewAttributeRealTime.Value != string.Empty)
                    NewElement.SetAttributeNode(NewAttributeRealTime);

                if (NewAttributeID.Value == string.Empty)
                    xmlnode.SelectSingleNode(elementName).InnerText = NewElement.InnerText;
                else
                {
                    xmlnode.InsertAfter(NewElement, xmlnode.LastChild);
                    xmldoc.DocumentElement.AppendChild(xmlnode);
                }

                xmldoc.Save(path);

                return "Element added.";
            }
            catch (Exception e)
            {
                return e.Message + "\r\nPlease try again.";
            }
        }
        
        internal static string RemoveFromXML(string elementID, string xPath, string elementName)
        {
            try
            {
                string path = getApplicationPath() + "AppConfig.xml";

                XmlDocument xmldoc = new XmlDocument();
                using (XmlReader xmlReader = XmlReader.Create(path))
                    xmldoc.Load(xmlReader);
				
                File.Copy(path, path + ".bak", true);
                File.Delete(path);
                    
                XmlNodeList xmlnodelist = xmldoc.SelectNodes(xPath + "/" + elementName + "[@id='" + elementID + "']");
                // Remove Handler
                for (int i = xmlnodelist.Count - 1; i >= 0 ; i--)
                {
                    XmlNode xmlnode = xmlnodelist[i];
                    xmlnode.ParentNode.RemoveChild(xmlnode);
                }
                // Remove Launcher
                xmlnodelist = xmldoc.SelectNodes(xPath + "/" + elementName + "[@id='*" + elementID + "']");
                for (int i = xmlnodelist.Count - 1; i >= 0 ; i--)
                {
                    XmlNode xmlnode = xmlnodelist[i];
                    xmlnode.ParentNode.RemoveChild(xmlnode);
                }
                    
                xmldoc.Save(path);

                return "Element removed.";
            }
            catch (Exception e)
            {
                return e.Message + "\r\nPlease try again.";
            }
        }
        
        internal static string getHelp(string chapter)
        {
            string _inset =     "1. Instruction Sets & Events\r\n" +
                                "   1.1 Add New Instruction Set\r\n" +
                                "       + judo inset add <lock>[ID]</lock> <lock>[Action]</lock>\r\n" +
                                "       + judo inset new <lock>[ID]</lock> <lock>[Action]</lock>\r\n" +
                                "       + judo inset set <lock>[ID]</lock> <lock>[Action]</lock>\r\n" +
                                "       + judo inset setup <lock>[ID]</lock> <lock>[Action]</lock>\r\n" +
                                "       + judo inset add [ID] <lock>[Action]</lock> `[Category]` `[Header]` `[Short  Description]` `[Long Description]` `[Thumbnail Url]` `[Real Time]`\r\n" +
                                "       + judo inset new [ID] <lock>[Action]</lock> `[Category]` `[Header]` `[Short  Description]` `[Long Description]` `[Thumbnail Url]` `[Real Time]`\r\n" +
                                "       + judo inset set [ID] <lock>[Action]</lock> `[Category]` `[Header]` `[Short  Description]` `[Long Description]` `[Thumbnail Url]` `[Real Time]`\r\n" +
                                "       + judo inset setup  [ID] <lock>[Action]</lock> `[Category]` `[Header]` `[Short Description]` `[Long Description]` `[Thumbnail Url]` `[Real Time]`\r\n" +
                                "   1.2 Remove Instruction Set\r\n" +
                                "       + judo inset remove <lock>[ID]</lock>\r\n" +
                                "       + judo inset delete <lock>[ID]</lock>\r\n" +
                                "       + judo inset del <lock>[ID]</lock>\r\n" +
                                "       + judo inset kill <lock>[ID]</lock>\r\n" +
                                "   1.3 List Items\r\n" +
                                "       + judo inset list\r\n" +
                                "       + judo inset ls\r\n" +
                                "   1.4 Add New Event Handler\r\n" +
                                "       + judo event add [ID] <lock>[Action]</lock>\r\n" +
                                "       + judo event new [ID] <lock>[Action]</lock>\r\n" +
                                "       + judo event set [ID] <lock>[Action]</lock>\r\n" +
                                "       + judo event setup [ID] <lock>[Action]</lock>\r\n" +
                                "   1.5 Remove Event Handler\r\n" +
                                "       + judo event remove [ID]\r\n" +
                                "       + judo event delete [ID]\r\n" +
                                "       + judo event del [ID]\r\n" +
                                "       + judo event kill [ID]\r\n" +
                                "   1.6 Delay Between Actions\r\n" +
                                "       + judo sleep [timeout in ms]\r\n" +
                                "       + judo timer [timeout in ms]\r\n" +
                                "   1.7 List Items\r\n" +
                                "       + judo event list\r\n" +
                                "       + judo event ls";
            string _mail =      "2. Mail\r\n" +
                                "   2.1 Smtp Settings\r\n" +
                                "       + judo smtp add [Host] [Username] [Password] [Port] [Ssl]\r\n" +
                                "       + judo smtp setup [Host] [Username] [Password] [Port] [Ssl]\r\n" +
                                "       + judo smtp set [Host] [Username] [Password] [Port] [Ssl]\r\n" +
                                "       + judo smtp settings\r\n" +
                                "   2.2 Pop3 Settings\r\n" +
                                "       + judo pop3 add [Host] [Username] [Password] [Port] [Ssl]\r\n" +
                                "       + judo pop3 setup [Host] [Username] [Password] [Port] [Ssl]\r\n" +
                                "       + judo pop3 set [Host] [Username] [Password] [Port] [Ssl]\r\n" +
                                "       + judo pop3 settings\r\n" +
                                "   2.3 Gmail Settings\r\n" +
                                "       + judo gmail add [Username] [Password]\r\n" +
                                "       + judo gmail setup [Username] [Password]\r\n" +
                                "       + judo gmail set [Username] [Password]\r\n" +
                                "       + judo gmail settings\r\n" +
                                "   2.4 Send\r\n" +
                                "       + judo mail send [From Address] [To Address] `[Subject]` `[Message]`";
            string _sms =       "3. SMS\r\n" +
                                "   3.1 Settings\r\n" +
                                "       + judo sms add [Api Id] [Username] [Password]\r\n" +
                                "       + judo sms setup [Api Id] [Username] [Password]\r\n" +
                                "       + judo sms set [Api Id] [Username] [Password]\r\n" +
                                "       + judo sms setings\r\n" +
                                "   3.2 Send\r\n" +
                                "       + judo sms send [Phone Number] [Message]";
            string _schedule =  "4. Scheduler\r\n" +
                                "   4.1 New Schedule\r\n" +
                                "       + judo schedule add [Name] [{single day: e.g.Monday} {d/m/yyyy} {daily} {workdays} {weekend}] [hh:mm] [{Instruction Set} || {Verbal Notification}]\r\n" +
                                "       + judo schedule new [Name] [{single day: e.g.Monday} {d/m/yyyy} {daily} {workdays} {weekend}] [hh:mm] [{Instruction Set} || {Verbal Notification}]\r\n" +
                                "       + judo schedule set [Name] [{single day: e.g.Monday} {d/m/yyyy} {daily} {workdays} {weekend}] [hh:mm] [{Instruction Set} || {Verbal Notification}]\r\n" +
                                "       + judo schedule setup [Name] [{single day: e.g.Monday} {d/m/yyyy} {daily} {workdays} {weekend}] [hh:mm] [{Instruction Set} || {Verbal Notification}]\r\n" +
                                "       + judo schedule add [Name] [{repeat} {timer} {interval}] [Interval in ms] [{Instruction Set} {Verbal Notification}]\r\n" +
                                "       + judo schedule new [Name] [{repeat} {timer} {interval}] [Interval in ms] [Instruction Set} {Verbal Notification}]\r\n" +
                                "       + judo schedule set [Name] [{repeat} {timer} {interval}] [Interval in ms] [Instruction Set} {Verbal Notification}]\r\n" +
                                "       + judo schedule setup [Name] [{repeat} {timer} {interval}] [Interval in ms] [Instruction Set} {Verbal Notification}]\r\n" +
                                "   4.2 Remove Schedule\r\n" +
                                "       + judo schedule remove [Name]\r\n" +
                                "       + judo schedule delete [Name]\r\n" +
                                "       + judo schedule del [Name]\r\n" +
                                "   4.3 Disable Schedule\r\n" +
                                "       + judo schedule disable [Name]\r\n" +
                                "       + judo schedule deactivate [Name]\r\n" +
                                "       + judo schedule stop [Name]\r\n" +
                                "       + judo schedule off [Name]\r\n" +
                                "   4.4 Enable Schedule\r\n" +
                                "       + judo schedule enable [Name]\r\n" +
                                "       + judo schedule activate [Name]\r\n" +
                                "       + judo schedule start [Name]\r\n" +
                                "       + judo schedule on [Name]\r\n" +
                                "   4.5 Remove All Schedules\r\n" +
                                "       + judo schedule remove-all\r\n" +
                                "       + judo schedule delete-all\r\n" +
                                "       + judo schedule del-all\r\n" +
                                "       + judo schedule cleanup\r\n" +
                                "       + judo schedule clear\r\n" +
                                "       + judo schedule empty\r\n" +
                                "   4.6 Disable All Schedules\r\n" +
                                "       + judo schedule disable-all\r\n" +
                                "       + judo schedule deactivate-all\r\n" +
                                "       + judo schedule stop-all\r\n" +
                                "       + judo schedule off-all\r\n" +
                                "   4.7 Enable All Schedules\r\n" +
                                "       + judo schedule enable-all\r\n" +
                                "       + judo schedule activate-all\r\n" +
                                "       + judo schedule start-all\r\n" +
                                "       + judo schedule on-all\r\n" +
                                "   4.8 List Actives [ Names ]\r\n" +
                                "       + judo schedule active\r\n" +
                                "       + judo schedule actives\r\n" +
                                "       + judo schedule active-list\r\n" +
                                "       + judo schedule active-ls\r\n" +
                                "       + judo schedule list-actives\r\n" +
                                "       + judo schedule ls-actives\r\n" +
                                "   4.9 List Inactives [ Names ]\r\n" +
                                "       + judo schedule inactive\r\n" +
                                "       + judo schedule inactives\r\n" +
                                "       + judo schedule inactive-list\r\n" +
                                "       + judo schedule inactive-ls\r\n" +
                                "       + judo schedule list-inactives\r\n" +
                                "       + judo schedule ls-inactives\r\n" +
                                "   4.10 List All [ Names ]\r\n" +
                                "       + judo schedule names\r\n" +
                                "       + judo schedule name-list\r\n" +
                                "       + judo schedule name-ls\r\n" +
                                "       + judo schedule list-names\r\n" +
                                "       + judo schedule ls-names\r\n" +
                                "   4.11 List Actives [ Details ]\r\n" +
                                "       + judo schedule active-details\r\n" +
                                "       + judo schedule actives-details\r\n" +
                                "       + judo schedule active-list-details\r\n" +
                                "       + judo schedule active-ls-details\r\n" +
                                "       + judo schedule list-actives-details\r\n" +
                                "       + judo schedule ls-actives-details\r\n" +
                                "   4.12 List Inactives [ Details ]\r\n" +
                                "       + judo schedule inactive-details\r\n" +
                                "       + judo schedule inactives-details\r\n" +
                                "       + judo schedule inactive-list-details\r\n" +
                                "       + judo schedule inactive-ls-details\r\n" +
                                "       + judo schedule list-inactives-details\r\n" +
                                "       + judo schedule ls-inactives-details\r\n" +
                                "   4.13 List All [ Details ]\r\n" +
                                "       + judo schedule details [Name (optional)]\r\n" +
                                "       + judo schedule list [Name (optional)]\r\n" +
                                "       + judo schedule ls [Name (optional)]\r\n" +
                                "       + judo schedule status [Name (optional)]\r\n" +
                                "       + judo schedule state [Name (optional)]";
            string _socket =    "5. Socket Communication\r\n" +
                                "   5.1 Start Service\r\n" +
                                "       + judo socket start\r\n" +
                                "       + judo socket enable\r\n" +
                                "       + judo socket on\r\n" +
                                "       + judo socket open\r\n" +
                                "       + judo socket listen\r\n" +
                                "   5.2 Stop Service\r\n" +
                                "       + judo socket stop\r\n" +
                                "       + judo socket disable\r\n" +
                                "       + judo socket off\r\n" +
                                "       + judo socket close\r\n" +
                                "   5.4 Setup\r\n" +
                                "       + judo socket set [Host] [Port]\r\n" +
                                "       + judo socket setup [Host] [Port]\r\n" +
                                "   5.5 Settings\r\n" +
                                "       + judo socket settings\r\n" +
                                "   5.6 Status\r\n" +
                                "       + judo socket status\r\n" +
                                "       + judo socket state";
            string _server =    "6. Web Server\r\n" +
                                "   6.1 Start\r\n" +
                                "       + judo server start\r\n" +
                                "       + judo server enable\r\n" +
                                "       + judo server on\r\n" +
                                "       + judo server listen\r\n" +
                                "   6.2 Stop\r\n" +
                                "       + judo server stop\r\n" +
                                "       + judo server disable\r\n" +
                                "       + judo server off\r\n" +
                                "   6.3 Change Login\r\n" +
                                "       + judo server login [Username] [Password]\r\n" +
                                "       + judo server cred [Username] [Password]\r\n" +
                                "       + judo server credentials [Username] [Password]\r\n" +
                                "   6.4 Setup\r\n" +
                                "       + judo server set [Host] [Port] [Authentication]\r\n" +
                                "       + judo server setup [Host] [Port] [Authentication]\r\n" +
                                "   6.5 Settings\r\n" +
                                "       + judo server settings\r\n" +
                                "   6.6 Status\r\n" +
                                "       + judo server status\r\n" +
                                "       + judo server state";
            string _serial =    "7. Serial Port\r\n" +
                                "   7.1 Open\r\n" +
                                "       + judo serial open [Port (optional)]\r\n" +
                                "   7.2 Close\r\n" +
                                "       + judo serial close\r\n" +
                                "   7.3 Send Command\r\n" +
                                "       + judo serial send [Command]\r\n" +
                                "   7.4 Setup\r\n" +
                                "       + judo serial set [Port] [Baud]\r\n" +
                                "       + judo serial setup [Port] [Baud]\r\n" +
                                "   7.5 Settings\r\n" +
                                "       + judo serial settings\r\n" +
                                "   7.6 Listen/Monitor\r\n" +
                                "       + judo serial listen [Timeout in ms (optional)]\r\n" +
                                "       + judo serial monitor [Timeout in ms (optional)]";
            string _cloud = "8. Web Services\r\n" +
                                "   8.1 Json Setup\r\n" +
                                //"       Create an instance (Instruction Set) for the response method.\r\n" +
                                "       + judo json add [ID] [Endpoint] [Node]\r\n" +
                                "       + judo json new [ID] [Endpoint] [Node]\r\n" +
                                "       + judo json set [ID] [Endpoint] [Node]\r\n" +
                                "       + judo json setup [ID] [Endpoint] [Node]\r\n" +
                                "   8.2 Json Response\r\n" +
                                "       + judo json get [Endpoint] [Node]\r\n" +
                                "       + judo json response [Endpoint] [Node]\r\n" +
                                "       + judo json consume [Endpoint] [Node]\r\n" +
                                "       + judo json extract [Endpoint] [Node]\r\n" +
                                "   8.3 Xml Setup [ Simple ]\r\n" +
                                "       + judo xml add [ID] [Endpoint] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml new [ID] [Endpoint] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml set [ID] [Endpoint] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml setup [ID] [Endpoint] [Node] [Attribute (optional)]\r\n" +
                                "   8.4 Xml Setup [ Namespace Prefix & Uri ]\r\n" +
                                "       + judo xml add [ID] [Endpoint] [Ns+Uri] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml new [ID] [Endpoint] [Ns+Uri] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml set [ID] [Endpoint] [Ns+Uri] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml setup [ID] [Endpoint] [Ns+Uri] [Node] [Attribute (optional)]\r\n" +
                                "   8.5 Xml Response [ Simple ]\r\n" +
                                "       + judo xml get [Endpoint] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml response [Endpoint] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml consume [Endpoint] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml extract [Endpoint] [Node] [Attribute (optional)]\r\n" +
                                "   8.6 Xml Response [ Namespace Prefix & Uri ]\r\n" +
                                "       + judo xml get [Endpoint] [Ns+Uri] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml response [Endpoint] [Ns+Uri] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml consume [Endpoint] [Ns+Uri] [Node] [Attribute (optional)]\r\n" +
                                "       + judo xml extract [Endpoint] [Ns+Uri] [Node] [Attribute (optional)]";
            string _help =      "9. Help\r\n" +
                                "   9.1 Preview All\r\n" +
                                "       + judo help\r\n" +
                                "       + judo ?\r\n" +
                                "   9.2 Preview Specific Category\r\n" +
                                "       + judo help [help keyword]\r\n" +
                                "       + judo ? [help keyword]\r\n\r\n" +
                                "   (*) Brackets are mandatory when place a sentence as one argument.\r\n" +
                                "   (**) <lock>parser protected document</lock> Lock tags used to bypass parser.\r\n" + 
                                "   (***) Help Keywords: inset, event, mail, sms, schedule, socket, server, serial, cloud, help";
            string _all =   _inset + "\r\n" +
                            _mail + "\r\n" +
                            _sms + "\r\n" +
                            _schedule + "\r\n" +
                            _socket + "\r\n" +
                            _server + "\r\n" +
                            _serial + "\r\n" +
                            _cloud + "\r\n" +
                            _help + "\r\n";

            switch (chapter)
            {
                case "inset":
                case "event":
                    return _inset;
                case "mail":
                    return _mail;
                case "sms":
                    return _sms;
                case "schedule":
                    return _schedule;
                case "socket":
                    return _socket;
                case "server":
                    return _server;
                case "serial":
                    return _serial;
                case "cloud":
                    return _cloud;
                case "help":
                    return _help;
                case "all":
                default:
                    return _all;
            }
        }
    }
    
    static class Queries
    {
        internal static String getRawData(string uri)
        {
            String rawData;

            using (var wc = new WebClient())
                rawData = wc.DownloadString(uri);

            return rawData;
        }

        internal class Xml
        {
            internal static List<String> SelectNodes(string Endpoint, string Node, string Attribute)
            {
                string[] nsprefixuri = Node.Split('=');
                string ns = nsprefixuri[0].Substring(nsprefixuri[0].LastIndexOf(':') + 1);
                string uri = nsprefixuri[1].Trim();

                string node = Attribute.Substring(0, Attribute.LastIndexOf('/'));
                string attr = Attribute.Substring(Attribute.LastIndexOf('/') + 1);

                return SelectNodes(Endpoint, ns, uri, node, attr);
            }

            private static List<String> SelectNodes(string Endpoint, string NamespacePrefix, string NamespaceUri, string Node, string Attribute)
            {
                XmlNodeList nodes = SelectNodeList(Endpoint, NamespacePrefix, NamespaceUri, Node);

                List<String> e = new List<String>();

                foreach (XmlNode node in nodes)
                    if (!String.IsNullOrEmpty(Attribute))
                        e.Add(node.Attributes[Attribute].InnerText);
                    else
                        e.Add(node.InnerText);

                return e;
            }

            internal static XmlNodeList SelectNodeList(string Endpoint, string NamespacePrefix, string NamespaceUri, string Node)
            {
                var xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(getRawData(Endpoint));

                var ns = new XmlNamespaceManager(xmlDoc.NameTable);
                ns.AddNamespace(NamespacePrefix, NamespaceUri);

                return xmlDoc.SelectNodes(Node, ns);
            }

            internal static String SelectSingleNode(string Endpoint, string Node, int NodeIndex)
            {
                try
                {
                    var xmlDoc = new XmlDocument();
                    xmlDoc.LoadXml(getRawData(Endpoint));

                    if (NodeIndex <= 0)
                        return xmlDoc.SelectNodes(Node).Item(0).InnerText;
                    else
                        return xmlDoc.SelectNodes(Node).Item(NodeIndex).InnerText;
                }
                catch
                {
                    return null;
                }
            }

            internal static String SelectSingleNode(string Endpoint, string Node)
            {
                return SelectSingleNode(Endpoint, Node, 0);
            }

            internal static XmlNodeList AppConfigQuery(string xPathNode)
            {
                try
                {
                    var xmlDoc = new XmlDocument();

                    xmlDoc.Load(Methods.getApplicationPath() + "AppConfig.xml");

                    return xmlDoc.SelectNodes(xPathNode);
                }
                catch
                {
                    return null;
                }
            }
        }

        internal class Json
        {
            // Json on line editor: http://codebeautify.org/online-json-editor
            internal String SelectSingleNode(string Endpoint, string Node)
            {
                string json = getRawData(Endpoint);

                JavaScriptSerializer serializer = new JavaScriptSerializer();
                dynamic item = serializer.Deserialize<object>(json);

                var steps = Node.Split('/');
                for (var i = 0; i < steps.Length; i++)
                {
                    int n;
                    if (int.TryParse(steps[i], out n))
                        item = item[n];
                    else
                        item = item[steps[i]];
                    if (item == null) return string.Empty;
                }

                return item.ToString();
            }
        }
    }
}